﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BezierApp
{
    /// <summary>
    /// Slow bezier superficie
    /// </summary>
    public class BezierSurface
    {
        public VertexBuffer VertexBuffer;
        public IndexBuffer IndexBuffer;
        public VertexDeclaration VertexDeclaration;
        public int PrimitiveCount;
        public int VerticesCount;
        BezierCurve c0;
        BezierCurve c1;
        BezierCurve c2;
        BezierCurve c3;
        Vector3[] dezesseisPontos;

        public BezierSurface(Vector3[] dezesseisPontos)
        {
            if (dezesseisPontos.Count() != 16)
                throw new Exception("16 pontos amigo");

            this.dezesseisPontos = dezesseisPontos;            
        }

        int size;
        float increment = 0.01f;
        public void Create(GraphicsDevice GraphicsDevice)
        {
            size = (int) ( 1f / increment);

            VertexPositionColor[] vertexList = new VertexPositionColor[size * size];
            short[] indexList = new short[(size - 1) * (size - 1) * 6 * 2];
            PrimitiveCount = indexList.Count() / 3;
            VerticesCount = vertexList.Count();

            c0 = new BezierCurve(dezesseisPontos[0], dezesseisPontos[1], dezesseisPontos[2], dezesseisPontos[3]);
            c1 = new BezierCurve(dezesseisPontos[4], dezesseisPontos[5], dezesseisPontos[6], dezesseisPontos[7]);
            c2 = new BezierCurve(dezesseisPontos[8], dezesseisPontos[9], dezesseisPontos[10], dezesseisPontos[11]);
            c3 = new BezierCurve(dezesseisPontos[12], dezesseisPontos[13], dezesseisPontos[14], dezesseisPontos[15]);

            float acum = 0;
            for (int i = 0; i < size; i ++)
            {

                Vector3 v0;
                Vector3 v1;
                Vector3 v2;
                Vector3 v3;

                v0 = c0.Evaluate(acum);
                v1 = c1.Evaluate(acum);
                v2 = c2.Evaluate(acum);
                v3 = c3.Evaluate(acum);
                acum += increment;

                BezierCurve hor = new BezierCurve(v0, v1, v2, v3);

                float acum2 = 0;
                for (int j = 0; j < size; j++)
                {                    
                    VertexPositionColor v;
                    v.Position = hor.Evaluate(acum2);
                    acum2 += increment;
                    v.Color = Color.White;
                    vertexList[size*i + j] = v;           
                }
                
            }

            //c0 = new BezierCurve(dezesseisPontos[0], dezesseisPontos[4], dezesseisPontos[8], dezesseisPontos[12]);
            //c1 = new BezierCurve(dezesseisPontos[1], dezesseisPontos[5], dezesseisPontos[9], dezesseisPontos[13]);
            //c2 = new BezierCurve(dezesseisPontos[2], dezesseisPontos[6], dezesseisPontos[10], dezesseisPontos[14]);
            //c3 = new BezierCurve(dezesseisPontos[3], dezesseisPontos[7], dezesseisPontos[11], dezesseisPontos[15]);


            //for (float i = 0; i < 1; i += 0.01f)
            //{

            //    Vector3 v0;
            //    Vector3 v1;
            //    Vector3 v2;
            //    Vector3 v3;

            //    v0 = c0.Evaluate(i);
            //    v1 = c1.Evaluate(i);
            //    v2 = c2.Evaluate(i);
            //    v3 = c3.Evaluate(i);

            //    BezierCurve hor = new BezierCurve(v0, v1, v2, v3);
            //}


            ///Tesselation da superficie
            int it = 0;
            for (int v = 0; v < size - 1; v++)            
            {
                for (int u = 0; u < size - 1; u++)
                {
                    // 0, 1, 2
                    indexList[it++] = (short)(size * (v + 0) + (u + 0));
                    indexList[it++] = (short)(size * (v + 0) + (u + 1));
                    indexList[it++] = (short)(size * (v + 1) + (u + 1));
                    
                    // 2, 3, 0
                    indexList[it++] = (short) (size * (v + 1) + (u + 1));
                    indexList[it++] = (short) (size * (v + 0) + (u + 1));
                    indexList[it++] = (short) (size * (v + 0) + (u + 0));
                }

            }
            
            for (int u = 0; u < size - 1; u++)
            {
                for (int v = 0; v < size - 1; v++)
                {                    
                    indexList[it++] = (short)(size * (v + 1) + (u + 1));
                    indexList[it++] = (short)(size * (v + 1) + (u + 0));
                    indexList[it++] = (short)(size * (v + 0) + (u + 0));

                    
                    indexList[it++] = (short)(size * (v + 0) + (u + 0));
                    indexList[it++] = (short)(size * (v + 1) + (u + 0));
                    indexList[it++] = (short)(size * (v + 1) + (u + 1));
                }

            }



            VertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);
            
            VertexBuffer = new VertexBuffer(GraphicsDevice, indexList.Length * VertexPositionColor.SizeInBytes, BufferUsage.WriteOnly);
            VertexBuffer.SetData(vertexList);

            IndexBuffer = new IndexBuffer(GraphicsDevice,typeof(short) ,indexList.Count(), BufferUsage.WriteOnly);
            IndexBuffer.SetData<short>(indexList);
        }        

        
    }
}
